﻿#include "tulingbox.h"
#include "ui_tulingbox.h"

TulingBox::TulingBox(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TulingBox)
{
    ui->setupUi(this);

    base_url=BASE_URL;
    key=AI_KEY;
    defaultTextFormat=ui->display->currentCharFormat();
    say(QStringLiteral("你好，")  + user.name + QStringLiteral("，我是您的AI助理，在此为您服务"));

    manager=new QNetworkAccessManager(this);
    connect(manager,&QNetworkAccessManager::finished,this,&TulingBox::replyFinished);
    ping();

    db=sp_createLocalStorage();
    if(!db_try())
        append(QStringLiteral("无法连接到数据库，无法使用本地命令"));
    else
    {
        cmdStore.connectStorage(db,TD_REF_CMD);
        bookmarks.connectStorage(db,TD_BOOKMARKS);
    }
}

TulingBox::~TulingBox()
{
    if(db.isOpen())
        db.close();

    delete ui;
}

bool TulingBox::db_try()
{
    if(!db.isOpen())
    {
        return db.open();
    }
    else
        return true;
}

void TulingBox::ping()
{
    pingReply = manager->get(QNetworkRequest(QUrl(base_url)));
    connect(pingReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(un_reach()));
}

void TulingBox::say(const QString &word)
{
    ui->display->append(word);
}

void TulingBox::append(const QString &word)
{
    ui->display->append(word);
}

void TulingBox::clear()
{
    ui->display->clear();
    ui->display->setCurrentCharFormat(defaultTextFormat);
    say(QStringLiteral("你好，")  + user.name + QStringLiteral("，我是您的AI助理，在此为您服务"));
}

void TulingBox::httpGet(const QString &url)
{
    manager->get(QNetworkRequest(QUrl(url)));
}

void TulingBox::httpPost(const QString &url, const QByteArray &data)
{
    QNetworkRequest request;
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setUrl(QUrl(url));

    manager->post(request,data);
}

void TulingBox::un_reach()
{
    pingReply->deleteLater();
    append(QStringLiteral("网络异常，无法连接到远程信息库"));
}

void TulingBox::replyFinished(QNetworkReply *reply)
{
    if(reply == pingReply)
        return;

    QJsonDocument doc=QJsonDocument::fromJson(reply->readAll());
    reply->deleteLater();

    if(!doc.isObject())
        return;

    QJsonObject obj=doc.object();
    if(obj.isEmpty())
        return;

    if(obj.contains("code"))
    {
        int code=obj.value("code").toInt();
        switch (code)
        {
        case T_TEXT:
        {
            QString text=obj.value("text").toString();
            say(text);
        }
            break;
        case T_URL:
        {
            QString text=obj.value("text").toString();
            say(text);

            QString url=obj.value("url").toString();
            processLink(url);
        }
            break;
        case T_NEWS:
        {
            QString text=obj.value("text").toString();
            say(text);

            QJsonArray array=obj.value("list").toArray();
            processNews(array);
        }
            break;
        case T_COOKBOOK:
        {
            QString text=obj.value("text").toString();
            say(text);

            QJsonArray array=obj.value("list").toArray();
            processCookbook(array);
        }
            break;
        default:
            say(doc.toJson());
        }
    }
}

void TulingBox::request(const QString &input)
{
    QJsonObject obj;
    obj.insert("info",input);
    obj.insert("key",key);

    QJsonDocument doc(obj);
    httpPost(base_url,doc.toJson());
}

void TulingBox::on_btn_submit_clicked()
{
    if(!_input.isEmpty())
        _input.clear();

    _input=ui->input->text().trimmed();
    if(_input.isEmpty())
        return;

    if(!cmdStore.isEmpty())
    {
        int code=cmdStore.parseCommand(_input);
        if(code != CMD_NULL)
            executeCommand(code);
        else
            request(_input);
    }
    else
        request(_input);

    ui->display->setCurrentCharFormat(defaultTextFormat);
    ui->display->append(QStringLiteral("我：") + _input);
    ui->input->clear();
}

void TulingBox::executeCommand(int code)
{
    switch (code) {
    case CMD_ACTION_EXIT:
        qApp->quit();
        break;
    case CMD_ACTION_SEARCH:
    {
        if(cmdStore.getArgs().isEmpty())
        {
            request(_input);
            return;
        }
        QString url=P_SEARCH +cmdStore.getArgs().first();
        QDesktopServices::openUrl(QUrl(url));
    }
        break;
    case CMD_BAIDU:
    {
        if(cmdStore.getArgs().isEmpty())
        {
            request(_input);
            return;
        }
        QString url=P_SEARCH +cmdStore.getArgs().first();
        QDesktopServices::openUrl(QUrl(url));
    }
        break;
    case CMD_TAOBAO:
    {
        if(cmdStore.getArgs().isEmpty())
        {
            request(_input);
            return;
        }
        QString url=P_TAOBAO +cmdStore.getArgs().first();
        QDesktopServices::openUrl(QUrl(url));
    }
        break;
    case CMD_ACTION_OPEN:
    {
        if(cmdStore.getArgs().isEmpty())
        {
            request(_input);
            return;
        }
        QString label=cmdStore.getArgs().first();
        bookmarks.open(label);
    }
        break;
    }
}

void TulingBox::processLink(const QString &link)
{
    QString url=QString(LINKS).arg(link).arg(QStringLiteral("戳我打开链接"));
    append(url);

    ui->display->append("\n");
}

void TulingBox::processNews(const QJsonArray &array)
{
    int length=array.size() > VIEW_NUM ? VIEW_NUM : array.size();

    for(int index=0;index < length;index ++)
    {
        QJsonObject obj=array.at(index).toObject();
        QString article=obj.value("article").toString();
        QString detailurl=obj.value("detailurl").toString();
        QString url=QString(LINKS).arg(detailurl).arg(article);
        append(url);
    }

    ui->display->append("\n");
}

void TulingBox::processCookbook(const QJsonArray &array)
{
    int length=array.size() > VIEW_NUM ? VIEW_NUM : array.size();

    for(int index=0;index < length;index ++)
    {
        QJsonObject obj=array.at(index).toObject();
        QString name=obj.value("name").toString();
        name = QStringLiteral("菜名：") + name;
        QString detailurl=obj.value("detailurl").toString();
        QString url=QString(LINKS).arg(detailurl).arg(name);
        append(url);

        QString info=obj.value("info").toString();
        append(QStringLiteral("食材：") +info);
    }

    ui->display->append("\n");
}
